package com.speedchina.common.download.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.speedchina.common.download.base.FieldConversion;
import com.speedchina.framework.utils.JSONUtils;
import com.speedchina.framework.utils.ReflectionUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author xz
 */
@Component
public class ExcelUtils<T>{

    /**
     * 实体模板填充
     * @date:  2021/5/14
     * @Description
     * @param  response, data, clazz, tableName data需要写入的数据，clazz导出模板对象，tableName文件名
     * @return void
     * @throws
     */
    public static void downLoadExcel(HttpServletResponse response,List data, Class clazz, String tableName){
        try {
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode(tableName , "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 传入需要导出的字段名
            Set<String> includeColumnFiledNames = new HashSet<String>();
            //获取到所有属性
            List<Field> allFields = ReflectionUtils.getAllFields(clazz);
            for (Field field : allFields) {
                //判断是否标有此注解
                if (field.isAnnotationPresent(ExcelProperty.class)){
                    //放入需要导出的字段名
                    includeColumnFiledNames.add(field.getName());
                }
            }
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(),clazz)
                    //.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) 自动列宽
                    //设置导出的字段
                    .includeColumnFiledNames(includeColumnFiledNames)
                    .autoCloseStream(Boolean.FALSE).sheet(tableName)
                    .doWrite(data);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            try {
                response.getWriter().println(JSONUtils.toJSONString(map));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }


    public static void  simpleFill(HttpServletResponse response,Object data, String tableName, String templateFileName) {
        if (null == data) {
            throw new NullPointerException();
        }
        try {
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode(tableName , "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 这里 会填充到第一个sheet， 然后文件流会自动关闭
            EasyExcel.write(response.getOutputStream(),data.getClass()).withTemplate(templateFileName).sheet().doFill(data);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            try {
                response.getWriter().println(JSONUtils.toJSONString(map));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 只对list进行填充
     * 导出数组则{.字段名}进行站位
     * @author: xz
     * @date:  2021/5/25
     * [response, data, tableName]
     * @return void
     * @throws
     */
    public static void downLoadExcelTemplate(HttpServletResponse response,Class clazz,List data, String tableName, String templateFileName){
        try {
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode(tableName , "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 这里 会填充到第一个sheet， 然后文件流会自动关闭
            EasyExcel.write(response.getOutputStream(),clazz).withTemplate(templateFileName).sheet().doFill(data);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            try {
                response.getWriter().println(JSONUtils.toJSONString(map));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 自定义模板导入：{字段名}进行站位
     * 若是导出数组则{.字段名}进行站位
     * 列表混合填充
     * @author: xz
     * @date:  2021/5/25
     * [response, data, tableName]
     * @return void
     * @throws
     */
    public static void excelTemplateCompositeFill(HttpServletResponse response,Class clazz,List listFill,HashMap fillMap, String tableName, String templateFileName){
        try {
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode(tableName , "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(),clazz).withTemplate(templateFileName).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            //对数组进行填充
            excelWriter.fill(listFill, writeSheet);
            //填充基础项
            excelWriter.fill(fillMap, writeSheet);
            excelWriter.finish();
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            try {
                response.getWriter().println(JSONUtils.toJSONString(map));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

}
